package com.linxuan.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.linxuan.reggie.common.R;
import com.linxuan.reggie.entity.User;
import com.linxuan.reggie.service.MailService;
import com.linxuan.reggie.service.UserService;
import com.linxuan.reggie.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private MailService mailService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 获取验证码操作
     *
     * @param user    使用User实体类加上RequestBody注解接收前端请求体中JSON格式数据
     * @return 返回用户是否登录成功
     */
    @PostMapping("/sendMsg")
    public R<String> sendMsg(@RequestBody User user) {
        // 获取前端传过来的用户email邮箱，这里使用phone接收一下
        String email = user.getPhone();
        // 设置邮箱的标题
        String subject = "瑞吉外卖";

        if (email != null) {
            // 生成验证码
            String code = ValidateCodeUtils.generateValidateCode(4).toString();
            // 打印验证码
            log.info("邮箱为 {} 的验证码为：{}", email, code);
            // 设置邮件文本
            String text = "【瑞吉外卖】您好，您的登录验证码为：" + code + "，请尽快登录，如非本人操作，请忽略此邮件。";
            // 发送邮件，如果嫌弃发送邮件麻烦可以将这行代码注释掉
            mailService.sendSimpleMail(email, subject, text);

            // 将验证码存入Redis中，key为邮箱，value为code，有效期限5分钟
            redisTemplate.opsForValue().set(email, code, 5, TimeUnit.MINUTES);

            // 发送成功
            return R.success("邮箱发送验证码邮件成功");
        }
        // 发送失败
        return R.error("邮箱发送验证码邮件失败");
    }

    /**
     * 前台用户登录功能
     *
     * @param map     使用Map接收请求体中JSON格式的数据
     * @param session 读取Session中保留的验证码
     * @return 返回用户信息
     */
    @PostMapping("/login")
    public R<User> login(@RequestBody Map<String, String> map, HttpSession session) {
        // 获取用户输入的邮箱，这里phone也存储邮箱
        String phone = map.get("phone");
        // 由于串池的存在，如果值相同，那么地址也会相同
        // 获取用户输入验证码
        String code = map.get("code");

        // 从redis中获取保存的验证码
        String codeInRedis = redisTemplate.opsForValue().get(phone);

        // 如果匹配成功
        if (code != null && code.equals(codeInRedis)) {
            // 查询数据库该邮箱对应用户信息
            LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(User::getPhone, phone);
            User user = userService.getOne(lambdaQueryWrapper);

            // 如果用户不存在那么就自动注册，向user表插入用户基本信息
            if (user == null) {
                // 重新创建新用户并为其赋值基本信息：邮箱、状态
                user = new User();
                user.setPhone(phone);
                user.setStatus(1);
                // 添加用户，执行完该操作，MP默认会将该user的userID赋值给该user，所以不用担心ID字段不存在
                userService.save(user);
            }

            // 存储用户ID
            session.setAttribute("user", user.getId());
            // 如果用户登录成功则删除Redis中缓存的验证码
            redisTemplate.delete(phone);

            log.info("存储用户ID：{}", user.getId());
            return R.success(user);
        }
        return R.error("登录失败");
    }

    /**
     * 前端用户退出功能
     *
     * @param session 删除Session域中保存的user信息
     * @return 返回退出成功
     */
    @PostMapping("/loginout")
    public R<String> loginout(HttpSession session) {
        // 清理Session中保存的当前用户登录的id
        session.removeAttribute("user");
        return R.success("退出成功");
    }

}
